﻿<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>1.依赖注入准备工作</title>
    <script type="text/javascript" src="../../Content/highlighter/scripts/shCore.js"></script>
    <script type="text/javascript" src="../../Content/highlighter/scripts/shBrushCSharp.js"></script>
    <link type="text/css" rel="stylesheet" href="../../Content/highlighter/styles/shCore.css" />
    <link type="text/css" rel="stylesheet" href="../../Content/highlighter/styles/shCoreEclipse.css" />
    <script type="text/javascript">SyntaxHighlighter.all();</script>
</head>
<body>
    <h3>1.依赖注入准备工作</h3>
        <b>声明接口与实现类</b>
        <pre class="brush: csharp">
            //1.定义IAnimal接口
            public interface IAnimal
            {
                void Talk();
            }
            //2.定义实现该IAnimal接口的Dog类
            public class Dog : IAnimal
            {
                public void Talk()
                {
                    Console.WriteLine("汪汪！");
                }
            }
            //3.定义实现该IAnimal接口的Cat类
            public class Cat : IAnimal
            {
                public void Talk()
                {
                    Console.WriteLine("喵喵！");
                }
            }
        </pre>
        <b>1.如果需要根据不同的情况调用不同的实现类</b>
        <pre class="brush: csharp">
        public static void Main(string[] args)
        {
            //根据用户输入调用不同的函数
            Char ch=Console.ReadKey();
            IAnimal animal;
            if(ch=='D')
            {
                animal=new Dog();
            }
            else
            {
                animal=new Cat();
            }
            //以上根据不同的情况调用不同的初始化函数需要和序员写代码
            animal.Talk();
        }
        </pre>
        <b>2.再进一步，解决需要手写代码调用不同Animal实现类的问题。</b>
        <pre class="brush: csharp">
        //该Dictionary类似于一个容器
        public static Dictionary&lt;Type,MethodInfo> container=new Dictionary&lt;Type,MethodInfo>();
        public static void Main(string[] args)
        {
            //【简单的实现】
            //1.注入时，把Dog注入到container容器中。其中接口类型作为key,实现类的初始化函数作为value，
            //GetConstructor()指获取该类型的初始化函数
            container.Add(typeof(IAnimal),typeof(Dog).GetConstructor());

            //2.执行时,通过接口类型从container容器中获取实现类的始化函数，然后再执行。
            MethodInfo constructor=container[typeof(IAnimal)];
            //3.Invoke(null,Type.EmptyTypes);指调用该初始化函数返回对象
            IAnimal animal= constructor.Invoke(null,Type.EmptyTypes);
            //4.调用Animal接口的Talk函数,输出：旺旺！
            animal.Talk();
            
            /*这时该container是不是很像一个容器，可以把Dog,Cat装进去，
              使用的时候调用的代码不需要作任何修改。这其实就是一个简单的依赖注入*/
        }
        </pre>
        <b>3.依托于配置文件的依赖注入</b>
        <pre class="brush: csharp">
        public static Dictionary&lt;Type,MethodInfo> container=new Dictionary&lt;Type,MethodInfo>();
        public static void Main(string[] args)
        {
            //【依托于配置文件的依赖注入】
            //1获取类型所在的程序集
            System.Reflection.Assembly assembly= System.Reflection.Assembly.Load("C:\assembly.dll");
            //2从配置文件中读取类型的名称,TypeName.txt中存储"Dog";
            string typeName=File.OpenText("C:\TypeName.txt").ReadToEnd();
            //3根据名称查找到该类型
            Type animalType= assembly.GetType(typeName);
            //4向容器中添加类型
            container.Add(typeof(IAnimal),animalType.GetConstructor());
            //5.执行时,通过接口类型查找到实现类的始化函数，然后再执行。
            MethodInfo constructor=container[typeof(IAnimal)];
            //6.Invoke(null,Type.EmptyTypes);指调用该初始化函数返回对象
            IAnimal animal= constructor.Invoke(null,Type.EmptyTypes);
            //7.调用Animal接口的Talk函数
            animal.Talk();
            /*最终效果是什么呢？如果TypeName.txt中的值为Dog，输出为"汪汪"，如果TypeName.txt中的值为Cat,输出为"喵喵"，
              即代码不需要做任何改动，即可调用不同的类。
              这个就是依赖注入的好处。*/
        }
        </pre>
</body>
</html>
